我在有時在撰寫 Java 程式時,會設計一些 API (Application Programming Interface) 讓別人來呼叫使用,你的 API 會產生一些例外需要呼叫的人來處理時,你就會在方法的宣告上使用 throws 這個關鍵字,意思就是丟出例外。
我們直接來看下面的例子:
package idv.jacky.ironman4;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Day15Example {
public void foo() throws IOException, FileNotFoundException {
try {
BufferedReader br = new BufferedReader(new FileReader("c:\\temp.txt"));
String line = br.readLine();
} catch (Exception e) {
throw e;
}
}
}
上面的程式碼裡,在第12行我們建立了一個 FileReader 的物件,要程式去開啟 c:\\temp.txt 這個檔案。在產生 FileReader 物件時,若無法找到指定的案,會丟出 FileNotFoundException。接著我們將產生好的 FileReader 物件傳入 BufferedReader 建構子,來產生 BufferedReader 的物件。第13行,我們使用 BufferedReader 物件所提供的 readLine 方法,來讀取檔案中的第一行資料。這個方法如果讀取失敗的話,會丟出 IOException。
因為第12、13行都有可能會丟出例外,所以我們在第14行用 catch 來處理它,因為懶得寫那麼多個 catch,所以就直接 catch Exception。可是我們希望呼叫這個方法的人,能進一步地處理這兩個例外,所以我們在 catch 區塊裡什麼也沒做,就直接又把例外丟出來。
如果我們要把例外丟出你的方法外的話,需要在方法的宣告上,明確的指定你這個方法會丟出什麼例外。所以我們就在第10行的方法宣告上宣告說,我會丟出 IOException 和 FileNotFoundException。
不幸地,這個例子在 Java SE 7 版之前是沒有辦法編譯的!因為我們在第14行已經透過多型轉型的方式,將 IOException 和 FileNotFoundException 轉成 Exception 型別了, 最後在第15行丟出來的是 Exception 型別,而不是 IOException 和 FileNotFoundException 型別。
所以在 Java SE 7 版之前,我們只有兩種方式來解決這個問題:
在方法的宣告上,直接宣告丟出 Exception
多重 catch 分別來處理
Java SE 7知道我們想要偷懶一點,所以剛剛這個例子直接拿去給 Java SE 7 編譯是會沒有錯誤地!也就是說 Java SE 7 的編譯器會很聰明地去檢查程式碼是不是只會丟出 IOException 和 FileNotFoundException 這兩種例外,所以你就可以偷懶囉~~